package experiment;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @ClassName SteamTest
 * @Date 2024/11/26 11:13 20
 * @Author Jack Chen
 * @Description serenity-cucumber-auto-project-jack
 * @Version 1.0
 */

public class SteamTest {
    public static void main(String[] args) {
        // 获取流，把集合/数组转换为Stream对象
        //把集合转为流
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("jack");
        arrayList.add("chen");
        arrayList.add("China");
        Stream<String> stream = arrayList.stream();
        stream.forEach(System.out::println);
        //把数组转为流
        Integer[] array = new Integer[]{2,1,4,5,3,4,1};
        Stream<Integer> stream1 = Arrays.stream(array);
        stream1.forEach(System.out::println);
        //直接创建流
        Stream<Integer> stream2 = Stream.of(1,2,3,4);
        stream2.forEach(System.out::println);

        /*
        流的操作：中间操作，流的各种数据处理，返回的还是流对象
         */

        //filter：过滤流中的某些元素
        //将数组array转为流，filter()将大于2的数据保留，forEach()输出
        Arrays.stream(array)
                .filter((e)->{return e>2;})
                .forEach((e)->{
                    System.out.println(e);//4，5，4
                });

        //sorted(): 自然排序，流中元素需实现 Comparable 接口
        //元素需实现了Comparable接口
        System.out.println("sorted自然排序:");
        Arrays.stream(array)
                .sorted()//int类型实现了Comparable接口，默认为升序
                .forEach((e)->{
                    System.out.println(e);//1 1 2 3 4 4 5
                });
        //降序
        System.out.println("sorted降序排序:");
        Arrays.stream(array)
                .sorted((o1,o2)->{
                    return o2-o1;
                })
                .forEach((e)->{
                    System.out.println(e);//5 4 4 3 2 1 1
                });

        //distinct: 去除重复元素
        //distinct()去除重复元素，将数组{2,1,4,5,3,4,1}的重复的1,4去掉
        System.out.println("distinct()去除重复元素:");
        Arrays.stream(array)
                .distinct()
                .forEach((e)->{
                    System.out.println(e);//2 1 4 5 3
                });

        //limit(n): 获取 n 个元素
        System.out.println("limit(n): 获取 n 个元素:");
        Arrays.stream(array)
                .limit(3)//从array中取出指定数量个元素，即前3个元素
                .forEach((e)->{
                    System.out.println(e);// 2 1 4
                });

        //skip(n): 跳过 n 元素，配合 limit(n)可实现分页
        System.out.println("skip(n): 跳过 n 元素，配合 limit(n)可实现分页:");
        Arrays.stream(array)
                .skip(3)//跳过指定数量个元素，排除前3个元素，生成一个新的stream对象
                .forEach((e)->{
                    System.out.println(e);// 5,3,4,1
                });

        //limit(m)与skip(n)同时使用时，若limit(m)在前，需要n<m，否者输出为空
        System.out.println("limit(m)与skip(n)同时使用时，若limit(m)在前，需要n<m，否者输出为空:");
        System.out.println(".limit(3).skip(3):");
        Arrays.stream(array)
                .limit(3)
                .skip(3)
                .forEach((e)->{
                    System.out.println(e);//无数值
                });

        System.out.println(".limit(3).skip(2):");
        Arrays.stream(array)
                .limit(3)
                .skip(2)
                .forEach((e)->{
                    System.out.println(e);//取前三个后，跳过前两个，输出4
                });

        System.out.println(".skip(2).limit(2):");
        Arrays.stream(array)
                .skip(2)
                .limit(2)
                .forEach((e)->{
                    System.out.println(e);//4 5，实现分页
                });

        //map(): 将其映射成一个新的元素
        System.out.println("map(): 将其映射成一个新的元素:");
        //arrayList集合中存入的数据为Student类型，map()将Student类的name成员变量映射到一个新的集合中
        ArrayList<Student> students = new ArrayList<>();
        students.add(new Student("jack", 123,1));
        students.add(new Student("lucky", 99,2));
        students.add(new Student("best story", 77,3));
        students.add(new Student("hard working", 66,4));
        Object[] s = students.stream()
                .map(Student::getName)
                .toArray();
        System.out.println(Arrays.toString(s));

        /*
        终端操作：返回的是我们需要的结果（数组，集合，单值）
         */

        //forEach: 遍历流中的元素(略)
        //toArray: 将流中的元素倒入一个数组
        System.out.println("toArray: 将流中的元素倒入一个数组:");
        Integer[] array1 = new Integer[]{11,4,5,1,4,19};
        Object[] s1 = Arrays.stream(array1)
                .distinct()
                .toArray();//将流中去重后的元素倒入一个数组中
        System.out.println(Arrays.toString(s1));//[11, 4, 5, 1, 19]

        //Min:返回流中元素最小值
        System.out.println("Min:返回流中元素最小值:");
        Integer min = Arrays.stream(array)
                .distinct()
                .min((o1, o2) -> {//最小值，实现了Comparable接口
                    return o1-o2;
                })
                .get();
        System.out.println(min);//1

        //Max:返回流中元素最大值
        System.out.println("Max:返回流中元素最大值:");
        Integer max = Arrays.stream(array)
                .distinct()
                .max((o1, o2) -> {//最大值，也实现Comparable接口了
                    return o1-o2;
                })
                .get();
        System.out.println(max);//19

        //count:返回流中元素的总个数
        System.out.println("count:返回流中元素的总个数:");
        long count = Arrays.stream(array)
                .distinct()//去重
                .count();//统计元素个数，返回值为long类型
        System.out.println(count);//5

        //Reduce:所有元素求和
        System.out.println("Reduce:所有元素求和:");
        long sum =  Arrays.stream(array)
                .reduce((a,b)->{//求和
                    return a+b;
                }).get();
        System.out.println(sum);//11+4+5+1+4+19 = 44

        //anyMatch:接收一个 Predicate 函数，只要流中有一个元素满足条件则返回 true，否则返回 false
        System.out.println("anyMatch:接收一个 Predicate 函数，只要流中有一个元素满足条件则返回 true，否则返回 false:");
        boolean result = Arrays.stream(array)
                .anyMatch((e)->{//有元素都满足条件，就返回true
                    return e>2;
                });
        System.out.println(result);

        //allMatch:接收一个 Predicate 函数，当流中每个元素都符合条件时才返回 true，否则返回 false
        System.out.println("allMatch:接收一个 Predicate 函数，当流中每个元素都符合条件时才返回 true，否则返回 false:);");
        boolean result1 = Arrays.stream(array)
                .allMatch((e)->{//所有元素都满足条件，才返回true
                    return e>2;
                });
        System.out.println(result1);//数组中有1，不满足条件，返回false


        //findFirst：返回流中第一个元素
        System.out.println("findFirst：返回流中第一个元素:");
        Integer s2 = Arrays.stream(array)
                .findFirst().
                get();
        System.out.println(s2);//11

        //collect:将流中的元素倒入一个集合,Collection 或 Map
        System.out.println("collect:将流中的元素倒入一个集合,Collection 或 Map:");
        Map map =  students.stream()
                .collect(Collectors
                        .toMap(Student::getId,Student::getName));//Student类中的id为键，name为值
        System.out.println(map);

        Set set = students.stream()
                .collect(Collectors.toSet());
        System.out.println(set);

        List list = students.stream()
                .collect(Collectors.toList());
        System.out.println(list);
    }
}
